﻿module WingBeats.CSS.Render

open WingBeats.CSS.SelectorParsing
open WingBeats.CSS.AST
open Common

let rec domainItemToString variables =
    function
    | Declaration (name, value)
        -> name + ":" + (value.GetValue(variables))
    | Collection (items)
        -> items |> List.map (domainItemToString variables) |> foldStrings ";"
    | DomainItemCreator _ as d
        -> d.GetValue() |> domainItemToString variables

let domainsToString variables domains =
    let addDescendantSpace (str : string) =
        if str.StartsWith(">") || str.StartsWith("~") || str.StartsWith("+")
            then str else " " + str

    let selectorToSelectors =
        let unParsedSelectorToString = function | Ast.UnparsedSelector str -> str
        Language.SelectorCollectionToSelectors >> List.map unParsedSelectorToString
    
    let rec buildOutput (acc, parentSelectors) (Domain(sel, attributes, subDomains)) = 
        let domainSelectors = sel |> selectorToSelectors
        let selector = 
            let addSubSelectors superSelector =
                domainSelectors 
                |> List.map( fun str -> superSelector + (str |> addDescendantSpace) )
                |> foldStrings ","
            let rec buildSelector =
                function
                | []         -> sel
                | parentSels ->
                    match parentSels with
                    | head :: []   -> addSubSelectors head
                    | head :: tail -> (addSubSelectors head) + "," + (buildSelector tail)
                    | []           -> ""
            buildSelector parentSelectors
        let attribString =
            let attribStrs = 
                attributes 
                |> List.map (domainItemToString variables)
            attribStrs
            |> foldStrings ";"
        let subDomainsStr = 
            subDomains 
            |> Seq.fold buildOutput ("", selector |> selectorToSelectors) 
            |> fst
        match attribString with
        | "" -> (acc + subDomainsStr, parentSelectors)
        | _  -> (acc + (sprintf "%s{%s}%s" selector attribString subDomainsStr), parentSelectors)

    domains |> Seq.fold buildOutput ("", []) |> fst

let stylesheetToString (Stylesheet (variables, domains)) =
    domains |> domainsToString variables